﻿using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.WebUtilities;
using Snowflake;
using System;
using System.Net.Http.Headers;

namespace Step4.Unit4.ModelBinding.Controllers
{
    public class UploadController : Controller
    {
        private readonly IWebHostEnvironment _webHostEnvironment;
        private readonly IdWorker _idWorker;

        public UploadController(IWebHostEnvironment webHostEnvironment)
        {
            _webHostEnvironment = webHostEnvironment;
            _idWorker = SnowflakeUtil.CreateIdWorker();
        }

        // (单文件上传)页面
        public IActionResult Index()
        {
            return View();
        }

        // (单文件上传) 上传提交
        // 文件默认大小，大概不能超过30M ！！！
        public IActionResult Single(IFormFile photo)
        {
            string extension = Path.GetExtension(photo.FileName);
            string[] supported = new string[] {"png","jpg","mp4","mp3" };
            if (!supported.Contains(extension))
            {
                return Ok("不支持当前文件后缀名。");
            }
            // 文件重命名
            var fileName = _idWorker.NextId() + "." + extension;// 使用雪花算法重命名文件，方式文件名重复 


            // 获取存储路径
            var filePath = Path.Combine(_webHostEnvironment.ContentRootPath, "upload", fileName);// ContentRootPath 是项目根目， WebRootPath是wwwroot
            using FileStream fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write);
            photo.CopyTo(fileStream); // 每次从文件流中拿80k,知道所有的字节流都被拷贝完成
            return Ok("上传成功！");
        }

        // (多文件上传)  页面
        public IActionResult MoreUpload()
        {
            return View();
        }


        /// <summary>
        /// 多文件上传
        /// </summary>
        /// <param name="photo"></param>
        /// <returns></returns>
        [HttpPost]
        public IActionResult MoreUpload(IFormFile[] photo)
        {
            foreach (var formFile in photo)
            {
                // 文件重命名
                var fileName = _idWorker.NextId() + "." + Path.GetExtension(formFile.FileName);// 使用雪花算法重命名文件，方式文件名重复 

                // 获取存储路径
                var filePath = Path.Combine(_webHostEnvironment.ContentRootPath, "upload", fileName);// ContentRootPath 是项目根目， WebRootPath是wwwroot
                using FileStream fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write);

                formFile.CopyTo(fileStream); // 每次从文件流中拿80k,知道所有的字节流都被拷贝完成
            }
            return Ok("上传成功！");
        }


        /// <summary>
        /// 大文件上传  页面
        /// </summary>
        /// <returns></returns>
        public IActionResult LargeFile()
        {
            return View();
        }

        // 不能使用IFormFile(不能超过30M)，那就只能从请求正文(body)中拿到文件(称为：流式上传)
        [HttpPost]
        [RequestFormLimits(MultipartBodyLengthLimit =609715200)]
        [RequestSizeLimit(609715200)]
        public async Task<IActionResult> UploadLargeFile()
        {
            var request = HttpContext.Request;
            if (!request.HasFormContentType || !MediaTypeHeaderValue.TryParse(request.ContentType, out var mediaTypeHeader) ||
                string.IsNullOrEmpty(GetBoundaryFromMideaType(mediaTypeHeader)))
            {
                return new UnsupportedMediaTypeResult();
            }
            var reader = new MultipartReader(GetBoundaryFromMideaType(mediaTypeHeader),request.Body);
            var section = await reader.ReadNextSectionAsync();  // 每次读取
            while (section != null)
            {
                var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var contentDisposition);

                if (hasContentDispositionHeader && contentDisposition.DispositionType.Equals("form-data") && 
                        !string.IsNullOrEmpty(contentDisposition.FileName))
                { 
                    // 获取文件后缀名
                    var extension = Path.GetExtension(contentDisposition.FileName);
                    extension = extension.Substring(1, extension.Length - 2);
                    // 文件重命名，方式文件重名(雪花算法)
                    var fileName = _idWorker.NextId() +"."+ extension;
                    var saveToPath = Path.Combine(_webHostEnvironment.ContentRootPath, "Upload", fileName);

                    using var targetStream = System.IO.File.Create(saveToPath);
                    await section.Body.CopyToAsync(targetStream); // 每次赋值80数据到目标文件流中
                }
            }

            return Ok("上传成功！");
        }


        private string GetBoundaryFromMideaType(MediaTypeHeaderValue mediaTypeHeader)
        {
            if (mediaTypeHeader.Parameters != null)
            {
                foreach (var paramer in mediaTypeHeader.Parameters)
                {
                    if (string.Equals(paramer.Name, "boundary", StringComparison.OrdinalIgnoreCase))
                    {
                        return paramer.Value;
                    }
                }
            }
            return null;
        }
    }
}
